__author__ = 'Aman'
from django.contrib.auth.decorators import login_required
from yaasapp.forms import CustomUserCreationForm
from django.shortcuts import render_to_response
from yaasapp.models import AuctionData, Biders
from django.shortcuts import render, redirect
from django.contrib.auth.views import logout
from django.http import HttpResponseRedirect
from django.contrib.auth.models import User
from yaasapp.wikify import html_to_content
from django.template import RequestContext
from django.core.mail import send_mail
from django.utils import translation
from django.http import HttpResponse
from django.contrib import auth
from datetime import datetime
import re

def register_user (request):
    if request.method == 'POST':
        form =CustomUserCreationForm(request.POST)
        if form.is_valid():
            new_user = form.save()
            auctionList = validAuction('sDate')
            return render_to_response("index.html",
                                      {'auction_list':auctionList,'msg':'New User is created. Please Login'},
                                      context_instance = RequestContext(request))
    else:
        form =CustomUserCreationForm(request.POST)

    return render_to_response("register/registration.html", {'form': form},context_instance= RequestContext(request))

@login_required(login_url='/login/')
def updateUser(request):
    if request.method == "POST":
        user = User.objects.get(username=request.user.username)

        email = str(request.POST['email'])
        password1 = str(request.POST['password1'])
        password2 = str(request.POST['password2'])
        if re.match("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$", email) ==None:
            return render_to_response("register/updateuser.html",
                                  {'uname':request.user.username,
                                   'email':email,
                                   'msg':'Email address was invalid.'},
                                    context_instance=RequestContext(request))
        elif password1 != password2 or password1=='' or password2=='':
            return render_to_response("register/updateuser.html",
                                  {'uname':request.user.username,
                                   'email':email,
                                   'msg':'Password didn\'t matched or it was empty.'},
                                    context_instance=RequestContext(request))

        if re.match("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$", email) !=None and password1==password2:
            user.email =email
            user.set_password(password1)
            user.save()
            return render_to_response("index.html",
                                      {'auction_list':validAuction('category'),
                                       'msg':'You information was successfully updated.',
                                       'logged_in':'logged'},
                                        context_instance=RequestContext(request))
    else:
        return render_to_response("register/updateuser.html",
                                  {'uname':request.user.username,
                                   'email':request.user.email,
                                   'msg':'Update the user.'},
                                    context_instance=RequestContext(request))

def login_view (request):
    auctionList = validAuction('sDate')
    if request.method == 'POST':
        username = request.POST.get('username', '')
        password = request.POST.get('password', '')
        user = auth.authenticate(username=username, password=password)
        if username == '' or password == '':
            return render_to_response("login.html", {'error': "Username/Password is empty."},
                                      context_instance = RequestContext(request))
        if user is not None and user.is_active:
            auth.login(request,user)
            if request.POST.get('nextto'):
			    return HttpResponseRedirect(request.POST.get('nextto'))
            return render_to_response("index.html",
                                      {'auction_list':auctionList,'msg':'Logged in as '+username,'logged_in':'logged'},
                                      context_instance = RequestContext(request))
        else:
            return render_to_response("login.html", {'error': "Username/Password is incorrect."},
                                      context_instance=RequestContext(request))
    else:
        return render_to_response("login.html", {'error': "Please Sign in"},
                                  context_instance= RequestContext(request))
    return render_to_response("index.html",
                              {'auction_list':auctionList,'msg':'Username/Password didn\' matched'},
                              context_instance = RequestContext(request))

def logout_view(request):
    logout(request)
    if request.POST.get('nextto'):
			    return HttpResponseRedirect(request.POST.get('nextto'))
    return redirect('/home/')

def language(request, lan ='en'):
    request.session["lang"] = lan
    translation.activate(request.session["lang"])
    return HttpResponseRedirect('/home/')

def home(request, sort_order=''):
    try:
        language(request, request.session["lang"])
    except:
        language(request, 'en')
    # This is for the search criteria
    if request.method == 'POST' and sort_order=='title':
        # This will check if the data with given title exists or not
        if AuctionData.existByTitle(request.POST['search']):
            auctionList = AuctionData.objects.filter(title = request.POST['search'])
        else:
            return render_to_response("index.html",
                                      {'msg':'No results were found.','logged_in':'logged'},
                                      context_instance = RequestContext(request))
    #Order the list of item by category
    elif sort_order and sort_order != 'title':
        auctionList = validAuction('category')
    #Order by the list of date, latest first.
    else:
        auctionList = validAuction('sDate')
    #Verify if the user is logged in or not.
    if request.user.is_authenticated():
        return render_to_response("index.html",
                                  {'auction_list':auctionList,'msg':'Logged in as '+request.user.username,'logged_in':'logged'},
                                  context_instance = RequestContext(request))
    else:
        return render_to_response("index.html",
                                  {'auction_list':auctionList},
                                  context_instance = RequestContext(request))

def itemDetail(request, id):
    try:
        language(request, request.session["lang"])
    except:
        language(request,'en')
    auctionList = validAuction('sDate')
    if request.method == 'POST':
        auction = AuctionData.getById(id)
        #If the price is more and has not been modified by other users before it was saved.
        if float(request.POST.get('c_price', '')) >= (float(auction.cPrice)+0.01) and request.POST.has_key("edited_version") and int(request.POST["edited_version"]) == auction.version:

                    auction.cPrice = request.POST.get('c_price', '')
                    auction.version = auction.version + 1
                    auction.save()
                    #Checks it the list of bider for the item is empty, if yes create one.
                    if not auction.bider.all():
                        bider = Biders(bider=request.user.username, bidDate=datetime.now(), bidItemID=auction.id)
                        bider.save()
                        auction.bider.add(bider)
                        emailView([(User.objects.get(username=auction.user)).email,request.user.email,],'Bid has been placed.','A Bid has been placed for this item.')
                    else:
                        boolean = False
                        listbider = [(User.objects.get(username=auction.user)).email,]
                        for i in auction.bider.all():
                            if str(i) == str(request.user.username):
                                boolean = True
                            listbider.append((User.objects.get(username=i)).email)
                        #If the list of bider exists then it checks if this bider has bidded or not If not.
                        if boolean == False:
                            bider = Biders(bider=request.user.username, bidDate=datetime.now(),bidItemID=auction.id)
                            bider.save()
                            auction.bider.add(bider)
                            emailView(listbider,'Bid has been increased.','A Bid has been increased for this item.')
                        #If bider has already bided for this item.
                        else:
                            # This will take place when the user has not bided to any other auction before and is only one in the list
                            try:
                                bider = Biders.objects.get(bider=request.user.username)
                                bider.bidDate = datetime.now()
                                bider.save(update_fields=['bidDate'])
                                emailView(listbider,'Bid has been increased.','A Bid has been increased for this item.')
                            # This will occurs when same user has bided for multiple auction and error will occurs as it happen to be saved in same table
                            except:
                                bider_list = Biders.objects.filter(bider=request.user.username)
                                for i in bider_list:
                                    if i.bidItemID == auction.id:
                                        i.bidDate = datetime.now()
                                        i.save(update_fields=['bidDate'])
                                emailView(listbider,'Bid has been increased.','A Bid has been increased for this item.')
                    return render_to_response("index.html",
                                              {'auction_list':auctionList, 'msg': 'The bid for '+auction.title+' has been increased.','logged_in':'logged'},
                                              context_instance=RequestContext(request))
        #If the price is more or has been modified by other users before it was saved.
        else:
            #If the price has been modified by other users before it was saved.
            if int(request.POST["edited_version"]) != auction.version:
                conf = 'The item description has been changed or the bid has been increased and now the current bid is '+str(auction.cPrice)
            else:
                conf = ''
            auc = AuctionData.getById(id)
            return render_to_response("item_edit.html",
                                      {'item_edit':'item',
                                       'auc': auc,
                                       'edited_version': auc.version,
                                       'biderList':auc.bider.all().order_by("-bidDate"),
                                       'c_price':float(auc.cPrice)+0.01,
                                       'msg':'Logged in as '+request.user.username,
                                       'logged_in':'logged','bid_user':'User Bid',
                                       'bid_invalid':'Minimum increase should be '+str(float(auction.cPrice)+0.01),
                                       'conflict':conf},
                                        context_instance=RequestContext(request))
    else:
        #Checks if the data exists in the database or not.
        if AuctionData.exists(id):
            auc = AuctionData.getById(id)
            # Checks if the user is banned.
            if auc.status == 'banned':
                return render_to_response("index.html",
                                              {'auction_list':auctionList, 'msg': 'This item has been banned by an administrator.','logged_in':'logged'},
                                              context_instance=RequestContext(request))
            message = 'Logged in as '+request.user.username
            status = ''
            if auc.status == 'due':
                message = 'This auction is due for adjucation and can not be bided any more.'
                status = 'due'
            if auc.status == 'winning':
                message = 'This auction is winning and can not be bided any more.'
                status = 'winning'
            if auc.status == 'aducated':
                message = 'This auction is aducated.'
                status = 'aducated'
                # Edit for the winning
            try:
                biderlist = auc.bider.all().order_by("-bidDate")
                cbider = biderlist[0]
                if str(cbider) == str(request.user.username):
                    message = 'At the moment you are winning this product. So you cant bid.'
                #If any user is logged in and is not the winner yet.
                if request.user.is_authenticated() and AuctionData.getById(id).user != request.user.username and str(cbider) != str(request.user.username):
                    return render_to_response("item_edit.html",
                                              {'item_edit':'item',
											   'auc': auc,
                                               'biderList':auc.bider.all().order_by("-bidDate"),
                                               'c_price':float(auc.cPrice)+0.01,
                                               'edited_version': auc.version,
                                               'msg':message,
                                               'logged_in':'logged',
                                               'bid_user':'bid_user',
                                               'status':status},
                                                context_instance=RequestContext(request))
                # If the Bidder is already winning the product
                if request.user.is_authenticated() and AuctionData.getById(id).user != request.user.username and str(cbider) == str(request.user.username):
                    return render_to_response("item_edit.html",
                                              {'item_edit':'item',
												'auc': auc,
                                               'biderList':auc.bider.all().order_by("-bidDate"),
                                               'c_price':float(auc.cPrice)+0.01,
                                               'edited_version': auc.version,
                                               'msg':message,
                                               'winning':'winner',
                                               'logged_in':'logged',
                                               'status':status},
                                                context_instance=RequestContext(request))
            # If the list of bidder is null meaning no bider is found
            except:
                if request.user.is_authenticated() and AuctionData.getById(id).user != request.user.username:
                    return render_to_response("item_edit.html",
                                              {'item_edit':'item',
												'auc': auc,
                                               'biderList':auc.bider.all().order_by("-bidDate"),
                                               'c_price':float(auc.cPrice)+0.01,
                                               'edited_version': auc.version,
                                               'msg':message,
                                               'logged_in':'logged',
                                               'bid_user':'bid_user',
                                               'status':status},
                                                context_instance=RequestContext(request))
            #Owner of the auction can not bid
            if request.user.is_authenticated() and AuctionData.getById(id).user == request.user.username:
                return render_to_response("item_edit.html",
                                          {'item_edit':'item',
											'auc': auc,
                                           'biderList':auc.bider.all().order_by("-bidDate"),
                                           'category': auc.category,
                                           'c_price':auc.cPrice,
                                           'msg':message,
                                           'logged_in':'logged'},
                                            context_instance=RequestContext(request))
            else:
                #If user is not logged in then he can only see the detail of auction but can't bid unless he has been logged in
                return render_to_response("item_edit.html",
                                          {'item_edit': 'item',
                                           'auc': auc,
                                           'biderList':auc.bider.all().order_by("-bidDate"),
                                           'c_price':auc.cPrice,
                                           'msg':'You are not logged in.',
                                           'a_owner': auc.aOwner},
                                            context_instance=RequestContext(request))
        #If the data doesnt exists in the database.
        else:
            return render_to_response("index.html",
                                      {'auction_list':auctionList,'msg':'This id doesn\'t exist.'},
                                      context_instance = RequestContext(request))

#Verify the user if has been logged in or not if not it will redirect the user to login page.
@login_required(login_url='/login/')
def newAuction(request):
    if not request.method == 'POST':
        return render(request, 'create_auction.html')
    else:
        if not request.POST['title']:
            e_title='Title can not be empty.'
        else:
            e_title=''
        if not request.POST['category']:
            e_category = 'Category can not be empty.'
        else:
            e_category = ''
        try:
            if (not isinstance(float(request.POST['cPrice']), float)) or (float(request.POST['cPrice']) < 0.1):
                e_cPrice='Price should be number and can not be empty or 0.'
            else:
                e_cPrice = ''
        except:
            e_cPrice='Price should be number and can not be empty or 0.'
        try:
            datetime.strptime(str(request.POST['eDate']), "%Y-%m-%d %H:%M")
            timediff = datetime.strptime(str(request.POST['eDate']), "%Y-%m-%d %H:%M") - datetime.now()
            hourdiff = timediff.total_seconds() / 60 / 60
            if hourdiff < 72:
                e_eDate = 'Minimum time for the auction should not be less than 72 hours.'
            else:
                e_eDate=''
        except:
            e_eDate='Date is either empty or does not match the format.'
        if not request.POST['aOwner']:
            e_aOwner='Owner field can not be empty.'
        else:
            e_aOwner=''
        #If the form is not valid, meaning the data are not entered correctly in the tables.
        if e_title or e_category or e_cPrice or e_eDate or e_aOwner:
            return render_to_response('create_auction.html', {"v_title": request.POST['title'],
                                                              "v_category": request.POST['category'],
                                                              "v_cPrice": request.POST['cPrice'],
                                                              "v_iDesc":request.POST['iDesc'],
                                                              "v_eDate": request.POST['eDate'],
                                                              "v_aOwner": request.POST['aOwner'],
                                                              "e_title":e_title,
                                                              "e_category":e_category,
                                                              "e_cPrice":e_cPrice,
                                                              "e_eDate":e_eDate,
                                                              "e_aOwner":e_aOwner},
                                                              context_instance=RequestContext(request))
        else:
            #Confirm weather to save the data to database or not.
            return render_to_response('confirm_auction.html', {"t_title": request.POST['title'].replace(' ',','),
                                                               "title": request.POST['title'],
                                                               "c_category": request.POST['category'],
                                                               "c_Price": request.POST['cPrice'],
                                                               "i_Desc":request.POST['iDesc'],
                                                               "e_Date": request.POST['eDate'].replace(' ',','),
                                                               "a_Owner": request.POST['aOwner']},
                                                                context_instance=RequestContext(request))

def saveAuction(request):
    option = request.POST.get('option', '')
    #This will save the auction data if every data entered was correct
    if option == 'Yes':
        auction = AuctionData(
                                  title=request.POST.get('t_title', '').replace(',', ' '),
                                  category=request.POST.get('c_category', ''),
                                  cPrice=request.POST.get('c_Price', ''),
                                  iDesc=request.POST.get('i_Desc', ''),
                                  sDate = datetime.now().strftime('%Y-%m-%d %H:%M'),
                                  user=request.user.username,status='active',
                                  eDate=request.POST.get('e_Date', '').replace(',', ' '),
                                  aOwner=request.POST.get('a_Owner', '')
                            )
        auction.save()
        emailView([request.user.email,],'Auction is created.','Auction has been created and sved.')
        auctionList = validAuction('sDate')
        return render_to_response("index.html",
                                  {'auction_list':auctionList,'msg':'New post has been saved','logged_in':'logged'},
                                  context_instance=RequestContext(request))
    #Discard the auction data if user selects NO. and redirect to the home page.
    else:
        auctionList = validAuction('sDate')
        return render(request, "index.html",
                               {'auction_list':auctionList,'msg':'Aunction was not saved.','logged_in':'logged'})

def edit_item(request, id):
    #If user is not logged in he will be directed to login page.
    if not request.user.is_authenticated():
        return HttpResponseRedirect('/login/?next=%s' % request.path)
    #If user is already logged in.
    else:
        auctionList = validAuction('sDate')
        #Checks if the user have a rights to edit the item or not. Meaning he is the owner of the item or not.
        if request.user.username == AuctionData.getById(id).user:
            #Checks if the data exists in the tables or not.
            if AuctionData.exists(id):
                auc = AuctionData.getById(id)
            else:
                return render_to_response("index.html",
                                          {'auction_list':auctionList,'msg':'This id doesn\'t exists.','logged_in':'logged'},
                                          context_instance=RequestContext(request))
            #If the item post exists in the database then he can edit it.
            if request.method == "POST" and request.POST.has_key("i_desc"):
                auc.iDesc = html_to_content(request.POST["i_desc"])
                auc.version = auc.version+1
                auc.save()
                return render_to_response("index.html",
                                          {'auction_list':auctionList,'msg':auc.title+' has been updated.','logged_in':'logged'},
                                          context_instance=RequestContext(request))
            if auc.status == 'banned':
                return render_to_response("index.html",
                                              {'auction_list':auctionList, 'msg': 'This item has been banned by an administrator.','logged_in':'logged'},
                                              context_instance=RequestContext(request))
            message = 'Logged in as '+request.user.username
            status = ''
            if auc.status == 'due':
                message = 'This auction is due for adjucation and can not be bided any more.'
                status = 'due'
            if auc.status == 'winning':
                message = 'This auction is winning and can not be bided any more.'
                status = 'winning'
            if auc.status == 'adjucated':
                message = 'This auction is adjucated.'
                status = 'adjucated'
            else:
                #GET and POST request are used when the modification is needed to be done
                return render_to_response("item_edit.html",
                                          {'item_edit':'edit',
                                           'auc':auc,
                                           'status':status,
                                           'msg':message,
                                           'logged_in':'logged'},
                                            context_instance=RequestContext(request))
        #If the user is not the owner of the item he can not edit and will be redirected to home page with a message
        else:
            return render_to_response("index.html",
                                      {'auction_list':auctionList,'msg':'You are not the owner of this item to edit.','logged_in':'logged'},
                                      context_instance=RequestContext(request))

def banAuction(request, id):
    try:
        auction = AuctionData.getById(id)
    except:
        return render_to_response("index.html",
                                      {'auction_list':validAuction('category'),
                                       'msg':'This id does not exist.',
                                       'logged_in':'logged'},
                                        context_instance=RequestContext(request))
    if request.user.is_authenticated() and request.user.is_superuser:
        auction.status = 'banned'
        auction.save(update_fields=['status'])
        biders = (auction.bider.all().order_by("-bidDate"))
        listofemail = [(User.objects.get(username=auction.user)).email,]
        for bid in biders:
            listofemail.append((User.objects.get(username=bid.bider)).email)
        emailView(listofemail,'Auction has been banned.','An auction '+auction.title+' has been banned by the admin.')
        return render_to_response("index.html",
                                  {'auction_list':validAuction('category'),
                                   'msg':'Auction named '+auction.title+' is banned.',
                                   'logged_in':'logged'},
                                    context_instance=RequestContext(request))
    else:
        if request.user.is_authenticated():
            return render_to_response("index.html",
                                      {'auction_list':validAuction('category'),
                                       'msg':'You are not an admin to ban an auction.',
                                       'logged_in':'logged'},
                                        context_instance=RequestContext(request))
        else:
            return render_to_response("index.html",
                                      {'auction_list':validAuction('category'),
                                       'msg':'You need to log in as admin to ban an auction.'},
                                        context_instance=RequestContext(request))

def validAuction(orderBy=''):
    if orderBy == '':
        auclist = AuctionData.objects.all()
    else:
        auclist = AuctionData.objects.all().order_by(orderBy)
    vAuc = []
    for auc in auclist:
        if auc.status == 'active':
            vAuc.append(auc)
        if str(auc.status) != 'adjudicated':
            if auc.eDate.strftime('%Y-%m-%d %H:%M') <= datetime.now().strftime('%Y-%m-%d %H:%M'):
                auc.status = 'due'
                auc.save(update_fields=['status'])
                biders = (auc.bider.all().order_by("-bidDate"))
                listofemail = [(User.objects.get(username=auc.user)).email,]
                for bid in biders:
                    listofemail.append((User.objects.get(username=bid.bider)).email)
                if biders and str(auc.status) != 'adjudicated':
                    auc.status = 'adjudicated'
                    auc.save(update_fields=['status'])
                    emailView([listofemail[1],],'Auction has been adjudicated.','Congratulations! You are the winner of auction '+auc.title+'.')
                    emailView(listofemail,'Auction has been adjudicated.','A Bid for the item has been adjudicated.')
                else:
                    auc.status = 'adjudicated'
                    auc.save(update_fields=['status'])
                    emailView(listofemail,'Auction has been adjudicated.','There was no bidder for this item till the end date.')
    return vAuc

def emailView(toEmail,subject,body ):
    from_email = 'noreply@yaas.com'
    send_mail(subject, body, from_email, toEmail, fail_silently=False)
    return HttpResponse('Email sent')